﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace KgUtils.Wpf
{
    /// <summary>
    /// Represents an <see cref="ICommand"/> which runs an event handler when it is invoked.
    /// </summary>
    /// <example>
    /// var cmd_annuler = new DelegateCommand(x => Annuler_Execute(), x => Annuler_CanExecute());
    /// </example>
    public class DelegateCommand : ICommand
    {
        private readonly Action<object> _executeAction;
        private readonly Predicate<object> _canExecute;

        /// <summary>
        /// Raised when changes occur that affect whether or not the command should execute.
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        /// <summary>
        /// Creates a new instance of <see cref="DelegateCommand"/> and assigns the given action to it.
        /// </summary>
        /// <param name="executeAction">Event handler to assign to the command.</param>
        public DelegateCommand(Action<object> executeAction)
            : this(executeAction, null)
        { }

        /// <summary>
        /// Creates a new instance of <see cref="DelegateCommand"/> and assigns the given action and predicate to it.
        /// </summary>
        /// <param name="executeAction">Event handler to assign to the command.</param>
        /// <param name="canExecute">Predicate to check whether the command can be executed.</param>
        public DelegateCommand(Action<object> executeAction, Predicate<object> canExecute)
        {
            _executeAction = executeAction;
            _canExecute = canExecute;
        }

        /// <summary>
        /// Defines the method that determines whether the command can execute in its current state.
        /// </summary>
        /// <returns>
        /// true if this command can be executed; otherwise, false.
        /// </returns>
        /// <param name="parameter">Data used by the command. If the command does not require data 
        /// to be passed, this object can be set to null.</param>
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute.Invoke(parameter);
        }

        /// <summary>
        /// Defines the method to be called when the command is invoked. The method will invoke the
        /// attached event handler.
        /// </summary>
        /// <param name="parameter">Data used by the command. If the command does not require data 
        /// to be passed, this object can be set to null.</param>
        public void Execute(object parameter)
        {
            _executeAction.Invoke(parameter);
        }
    }
}
